import java.util.LinkedList;
import java.util.Queue;

// 多道程序设计实现
public class Main {

    public program[] pro;


    public Queue<program> CPU;          // cpu队列
    public Queue<program> PassageOne;   // 通道1
    public Queue<program> PassageTwo;   // 通道2
    public program temp;                // 临时变量，暂时保存一个进程

    int nowTime;
    int nowPro;

    public Main(int nowTime, int nowPro) {
        this.nowTime = nowTime;
        this.nowPro = nowPro;

        pro = new program[101];
        pro[0] = new program(30,40,10,0);
        pro[1] = new program(60,30,10,1);
        pro[2] = new program(20,40,20,2);
        pro[3] = new program(0,0,0,100);


        CPU = new LinkedList<>();
        PassageOne = new LinkedList<>();
        PassageTwo = new LinkedList<>();
    }

    public static void main(String[] args) {

        Main m = new Main(0, 0);
        m.multiChannelPreemptive();
        //m.multiChannelNonPreemptive();

        //m.singleChannelProceemptive();
        //m.singleChannelNonProceemptive();

    }

    //双通道抢占
    public void runPro4()
    {
        if (CPU.peek().level == 100)	return;
        if (!PassageOne.isEmpty())
        {
            if (PassageOne.peek().level == CPU.peek().level)
            {
                CPU.poll();
                return;
            }
        }
        if (!PassageTwo.isEmpty())
        {
            if (PassageTwo.peek().level == CPU.peek().level)
            {
                CPU.poll();
                return;
            }
        }
        if (CPU.peek().countOne > 0)
        {
            CPU.peek().countOne--;
            if (CPU.peek().countOne == 0)
            {
                temp = CPU.peek();
                CPU.poll();
                pro[temp.level] = temp;
                if (PassageOne.isEmpty())
                    PassageOne.add(temp);
                else if (PassageTwo.isEmpty())
                    PassageTwo.add(temp);
            }
        }
        else
        {
            if (CPU.peek().countTwo > 0)
            {
                CPU.peek().countTwo--;
                if (CPU.peek().countTwo == 0)
                {
                    temp = CPU.peek();
                    CPU.poll();
                    pro[temp.level] = temp;
                }
            }
        }
    }

    public void runIO4()
    {
        if (!PassageOne.isEmpty())
        {
            PassageOne.peek().IO--;
            if (PassageOne.peek().IO == 0)
            {
                temp = PassageOne.peek();
                PassageOne.poll();
                pro[temp.level] = temp;
                if (!CPU.isEmpty() && temp.level < CPU.peek().level)
                {
                    CPU.add(temp);
                    temp = CPU.peek();
                    pro[temp.level] = temp;
                    CPU.poll();
                }
                if (CPU.isEmpty())
                {
                    CPU.add(temp);
                }
            }
        }
        if (!PassageTwo.isEmpty())
        {
            PassageTwo.peek().IO--;
            if (PassageTwo.peek().IO == 0)
            {
                temp = PassageTwo.peek();
                PassageTwo.poll();
                pro[temp.level] = temp;
                if (temp.level < CPU.peek().level)
                {
                    CPU.add(temp);
                    temp = CPU.peek();

                    pro[temp.level] = temp;
                    CPU.poll();
                }
                if (CPU.isEmpty())
                {
                    CPU.add(temp);
                }
            }
        }
    }

    public void multiChannelPreemptive()
    {
        CPU.add(pro[0]);
        while (true)
        {
            nowTime++;

            runPro4();
            runIO4();

            while (CPU.isEmpty())
            {
                if (pro[nowPro].countOne != 0)	CPU.add(pro[nowPro]);
                else if (pro[nowPro].countOne == 0 && pro[nowPro].IO != 0)	CPU.add(pro[nowPro + 1]);
                else if (pro[nowPro].countOne == 0 && pro[nowPro].countTwo == 0)	nowPro++;
                if (nowPro > 2)	break;
            }
            if (pro[2].countTwo == 0)	break;
        }
        System.out.println("三道程序运行结束需要 " + (nowTime + 1) + "MS");


    }

    //双通道非抢占
    public void runPro3()
    {
        // peek方法 表示获取队首元素
        if (CPU.peek().level == 100 && CPU.size() == 1) {
            CPU.poll();
            return;
        }
        if (!PassageOne.isEmpty())   // 如果通道1不为空
        {
            // 当通道1的队首元素的优先级和cpu队列的队首元素优先级一致时，说明两个进程一致
            if (PassageOne.peek().level == CPU.peek().level)
            {
                CPU.poll();   // poll方法表示移除队列的第一个元素
                return;
            }
        }
        if (!PassageTwo.isEmpty())
        {
            if (PassageTwo.peek().level == CPU.peek().level)
            {
                CPU.poll();
                return;
            }
        }
        if (CPU.peek().countOne > 0)
        {
            CPU.peek().countOne--;
            if (CPU.peek().countOne == 0)
            {
                temp = CPU.peek();
                CPU.poll();

                //更新pro中的进程信息
                pro[temp.level] = temp;
                if (PassageOne.isEmpty())
                    PassageOne.add(temp);
                else if (PassageTwo.isEmpty())
                    PassageTwo.add(temp);
            }
        }
        else
        {
            if (CPU.peek().countTwo > 0)
            {
                CPU.peek().countTwo--;
                if (CPU.peek().countTwo == 0)
                {
                    temp = CPU.peek();
                    CPU.poll();

                    //更新pro中的进程信息， 刚好level的值和下标相对应
                    pro[temp.level] = temp;
                }
            }

        }
    }
    
    public void runIO3()
    {
        if (!PassageOne.isEmpty())
        {
            PassageOne.peek().IO--;
            if (PassageOne.peek().IO == 0)
            {
                temp = PassageOne.peek();
                PassageOne.poll();
                pro[temp.level] = temp;

                CPU.add(temp);
            }
        }
        if (!PassageTwo.isEmpty())
        {
            PassageTwo.peek().IO--;
            if (PassageTwo.peek().IO == 0)
            {
                temp = PassageTwo.peek();
                PassageTwo.poll();
                pro[temp.level] = temp;

                CPU.add(temp);
            }
        }
    }

    public void multiChannelNonPreemptive()
    {
        // 将第一个进程添加到cpu队列中
        CPU.add(pro[0]);

        while (true)
        {
            nowTime++;

            // 执行cpu运算
            runPro3();
            // 进行io
            runIO3();

            // 当cpu队列为空时，将一个进程加入cpu队列
            // nowPro 是当前正在运行的进程
            while (CPU.isEmpty())
            {
                // nowPro是一个数组下标 代表当前进程
                if (pro[nowPro].countOne != 0)
                {
                    // 当前进程的第一次运算时间不为0时，将当前进程加载入cpu队列
                    CPU.add(pro[nowPro]);
                }
                else if (pro[nowPro].countOne == 0 && pro[nowPro].IO != 0)
                {

                    //当前进程第一次运算时间为0，io时间不为0时，说明当前进程正在进行io，将下一个进程加载入cpu队列
                    CPU.add(pro[nowPro + 1]);
                }
                else if (pro[nowPro].countOne == 0 && pro[nowPro].countTwo == 0)
                {
                    //当前进程第二次计算时间为0，说明当前进程已经运行结束
                    nowPro++;
                }
                if (nowPro > 2)	break;
            }
            if (pro[2].countTwo == 0)	break;
        }
        System.out.println("三道程序运行结束需要 " + (nowTime+1) + "MS");

    }

    //单通道抢占
    public void runPro2()
    {

        if (CPU.peek().level == 100)	return;
        if (!PassageOne.isEmpty())
        {
            if (PassageOne.peek().level == CPU.peek().level)
            {
                CPU.poll();
                return;
            }
        }

        if (CPU.peek().countOne > 0)
        {
            CPU.peek().countOne--;
            if (CPU.peek().countOne == 0)
            {
                temp = CPU.peek();
                CPU.poll();

                pro[temp.level] = temp;

                PassageOne.add(temp);
            }
        }
        else
        {
            if (CPU.peek().countTwo > 0)
            {
                CPU.peek().countTwo--;
                if (CPU.peek().countTwo == 0)
                {
                    temp = CPU.peek();
                    CPU.poll();
                    pro[temp.level] = temp;
                }
            }
        }
    }
    public void runIO2()
    {

        if (!PassageOne.isEmpty())
        {
            if (PassageOne.peek().level == 2 && PassageOne.peek().IO == 38) PassageOne.peek().countTwo = 20;
            PassageOne.peek().IO--;
            if (PassageOne.peek().IO == 0)
            {
                temp = PassageOne.peek();
                PassageOne.poll();

                pro[temp.level] = temp;
                if (!CPU.isEmpty() && temp.level < CPU.peek().level)
                {
                    CPU.add(temp);
                    temp = CPU.peek();
                    pro[temp.level] = temp;
                    CPU.poll();
                }
                if (CPU.isEmpty())
                {
                    CPU.add(temp);
                }
            }
        }

    }

    public void singleChannelProceemptive()
    {
        // 将第一个进程添加到cpu队列中
        CPU.add(pro[0]);

        while (true)
        {
            nowTime++;

            // 执行cpu运算
            runPro2();
            // 进行io
            runIO2();

            // 当cpu队列为空时，将一个进程加入cpu队列
            // nowPro 是当前正在运行的进程
            while (CPU.isEmpty())
            {
                // nowPro是一个数组下标 代表当前进程
                if (pro[nowPro].countOne != 0)
                {
                    // 当前进程的第一次运算时间不为0时，将当前进程加载入cpu队列
                    CPU.add(pro[nowPro]);
                }
                else if (pro[nowPro].countOne == 0 && pro[nowPro].IO != 0)
                {

                    //当前进程第一次运算时间为0，io时间不为0时，说明当前进程正在进行io，将下一个进程加载入cpu队列
                    CPU.add(pro[nowPro + 1]);
                }
                else if (pro[nowPro].countOne == 0 && pro[nowPro].countTwo == 0)
                {
                    //当前进程第二次计算时间为0，说明当前进程已经运行结束

                    nowPro++;
                }
                if (nowPro > 2)	break;
            }
            if (pro[2].countTwo == 0)	break;
        }
        System.out.println("三道程序运行结束需要 " + (nowTime + 1) + "MS");

    }

    //单通道非抢占
    public void runPro1()
    {
        // peek方法 表示获取队首元素
        if (CPU.peek().level == 100 && CPU.size() == 1) {
            CPU.poll();
            return;
        }
        if (CPU.peek().level == 100)	return;
        if (!PassageOne.isEmpty())
        {
            if (PassageOne.peek().level == CPU.peek().level)
            {
                CPU.poll();
                return;
            }
        }

        if (CPU.peek().countOne > 0)
        {
            CPU.peek().countOne--;
            if (CPU.peek().countOne == 0)
            {
                temp = CPU.peek();
                CPU.poll();
                pro[temp.level] = temp;

                PassageOne.add(temp);
            }
        }
        else
        {
            if (CPU.peek().countTwo > 0)
            {
                CPU.peek().countTwo--;
                if (CPU.peek().countTwo == 0)
                {
                    temp = CPU.peek();
                    CPU.poll();
                    pro[temp.level] = temp;
                }
            }
        }
    }
    public void runIO1()
    {
        if (!PassageOne.isEmpty())
        {
            PassageOne.peek().IO--;
            if (PassageOne.peek().IO == 0)
            {
                temp = PassageOne.peek();
                PassageOne.poll();
                pro[temp.level] = temp;

                CPU.add(temp);

            }
        }

    }

    public void singleChannelNonProceemptive()
    {
        // 将第一个进程添加到cpu队列中
        CPU.add(pro[0]);

        while (true)
        {
            nowTime++;

            // 执行cpu运算
            runPro1();
            // 进行io
            runIO1();

            // 当cpu队列为空时，将一个进程加入cpu队列
            // nowPro 是当前正在运行的进程
            while (CPU.isEmpty())
            {
                // nowPro是一个数组下标 代表当前进程
                if (pro[nowPro].countOne != 0)
                {
                    // 当前进程的第一次运算时间不为0时，将当前进程加载入cpu队列
                    CPU.add(pro[nowPro]);
                }
                else if (pro[nowPro].countOne == 0 && pro[nowPro].IO != 0)
                {

                    //当前进程第一次运算时间为0，io时间不为0时，说明当前进程正在进行io，将下一个进程加载入cpu队列
                    CPU.add(pro[nowPro + 1]);
                }
                else if (pro[nowPro].countOne == 0 && pro[nowPro].countTwo == 0)
                {
                    //当前进程第二次计算时间为0，说明当前进程已经运行结束

                    nowPro++;
                }
                if (nowPro > 2)	break;
            }
            if (pro[2].countTwo == 0)	break;
        }
        System.out.println("三道程序运行结束需要 " + (nowTime + 1) + "MS");
    }
}
